﻿namespace SERFLITEMAX20.Core
{
    using SERFLITEMAX20;
    using System;
    using System.Xml;

    public abstract class BaseObject
    {
        private int entry = 0;
        private long guid;
        internal bool invalid = false;
        internal int ptrBase;
        internal int ptrStorage;
        internal int ptrStorageEnd;
        internal Main sender;
        private enObjectTypes type;

        internal BaseObject(int ptr, Main sender)
        {
            this.ptrBase = ptr;
            this.sender = sender;
            this.type = (enObjectTypes) sender.Memory.ReadInteger(this.ptrBase + Addresses.OFFSET_OBJECT_TYPE);
            this.ptrStorage = sender.Memory.ReadInteger(this.ptrBase + Addresses.OFFSET_OBJECT_STORAGE_POINTER_START);
            this.ptrStorageEnd = sender.Memory.ReadInteger(this.ptrBase + Addresses.OFFSET_OBJECT_STORAGE_POINTER_END);
            this.guid = this.ReadStorageLong(UpdateFields.OBJECT_FIELD_GUID);
        }

        public XmlElement GetBaseXMLElement(XmlDocument pDom)
        {
            return this.GetBaseXMLElement(pDom, "object");
        }

        public XmlElement GetBaseXMLElement(XmlDocument pDom, string pName)
        {
            XmlElement element = pDom.CreateElement(pName);
            element.SetAttribute("guid", this.guid.ToString());
            element.SetAttribute("entry", this.Entry.ToString());
            element.SetAttribute("type", ((int) this.type).ToString());
            return element;
        }

        public float GetDistance(BaseObject obj)
        {
            if (obj == null)
            {
                return 0f;
            }
            return this.GetDistance(obj.X, obj.Y, obj.Z);
        }

        public float GetDistance(float x, float y, float z)
        {
            float num = this.X - x;
            float num2 = this.Y - y;
            float num3 = (z != 0f) ? (this.Z - z) : 0f;
            return (float) Math.Sqrt((double) (((num * num) + (num2 * num2)) + (num3 * num3)));
        }

        public float GetFaceRadian(float faceX, float faceY)
        {
            float num = this.X - faceX;
            float num2 = faceY - this.Y;
            float num3 = 0f;
            if ((num > 0.0) && (num2 >= 0.0))
            {
                num3 = (float) Math.Atan((double) (num2 / num));
            }
            if ((num < 0.0) && (num2 >= 0.0))
            {
                num3 = ((float) Math.Atan((double) (num2 / num))) + 3.141593f;
            }
            if ((num < 0.0) && (num2 < 0.0))
            {
                num3 = ((float) Math.Atan((double) (num2 / num))) + 3.141593f;
            }
            if ((num > 0.0) && (num2 < 0.0))
            {
                num3 = ((float) Math.Atan((double) (num2 / num))) + 6.283185f;
            }
            return (num3 - 1.570796f);
        }

        public virtual XmlElement GetXMLElement(XmlDocument pDom)
        {
            return this.GetBaseXMLElement(pDom, "object");
        }

        public virtual XmlElement GetXMLElement(XmlDocument pDom, string pName)
        {
            return this.GetBaseXMLElement(pDom, pName);
        }

        public byte ReadPtrBaseByte(int field)
        {
            return this.sender.Memory.ReadByte(this.ptrBase + field);
        }

        public int ReadPtrBaseInt(int field)
        {
            return this.sender.Memory.ReadInteger(this.ptrBase + field);
        }

        public byte ReadStorageByte(UpdateFields field, int pos)
        {
            return this.ReadStorageByte((int) field, pos);
        }

        public byte ReadStorageByte(int field, int pos)
        {
            if (((this.ptrStorage + field) + pos) > this.ptrStorageEnd)
            {
                return 0;
            }
            return this.sender.Memory.ReadByte((this.ptrStorage + field) + pos);
        }

        public float ReadStorageFloat(UpdateFields field)
        {
            return this.ReadStorageFloat((int) field);
        }

        public float ReadStorageFloat(int field)
        {
            int num = field * 4;
            if ((this.ptrStorage + num) > this.ptrStorageEnd)
            {
                return -1f;
            }
            return this.sender.Memory.ReadFloat(this.ptrStorage + num);
        }

        public int ReadStorageInt(UpdateFields field)
        {
            return this.ReadStorageInt((int) field);
        }

        public int ReadStorageInt(int field)
        {
            int num = field * 4;
            if ((this.ptrStorage + num) > this.ptrStorageEnd)
            {
                return -1;
            }
            return this.sender.Memory.ReadInteger(this.ptrStorage + num);
        }

        public long ReadStorageLong(UpdateFields field)
        {
            return this.ReadStorageLong((int) field);
        }

        public long ReadStorageLong(int field)
        {
            int num = field * 4;
            if ((this.ptrStorage + num) > this.ptrStorageEnd)
            {
                return -1L;
            }
            return this.sender.Memory.ReadLong(this.ptrStorage + num);
        }

        public virtual bool Update()
        {
            if (!this.IsValid)
            {
                return false;
            }
            this.type = (enObjectTypes) this.sender.Memory.ReadInteger(this.ptrBase + Addresses.OFFSET_OBJECT_TYPE);
            return true;
        }

        public int BasePtr
        {
            get
            {
                return this.ptrBase;
            }
        }

        public virtual bool CanLoot
        {
            get
            {
                return false;
            }
        }

        internal virtual long ChannelObjectGUID
        {
            get
            {
                return 0L;
            }
        }

        public virtual long CharmGuid
        {
            get
            {
                return 0L;
            }
        }

        public virtual long CreatedBy
        {
            get
            {
                return 0L;
            }
        }

        public virtual int DisplayID
        {
            get
            {
                return 0;
            }
        }

        public virtual int DynFlags
        {
            get
            {
                return 0;
            }
        }

        public int Entry
        {
            get
            {
                if (this.entry == 0)
                {
                    this.entry = this.ReadStorageInt(UpdateFields.OBJECT_FIELD_ENTRY);
                }
                return this.entry;
            }
        }

        public virtual float Facing
        {
            get
            {
                return 0f;
            }
        }

        public virtual int Flags
        {
            get
            {
                return 0;
            }
        }

        public long Guid
        {
            get
            {
                return this.guid;
            }
        }

        public virtual int Health
        {
            get
            {
                return 0;
            }
        }

        public virtual float HealthPercentage
        {
            get
            {
                return 0f;
            }
        }

        public virtual bool IsDead
        {
            get
            {
                return false;
            }
        }

        public virtual bool IsInCombat
        {
            get
            {
                return false;
            }
        }

        public virtual bool IsSitting
        {
            get
            {
                return false;
            }
        }

        public virtual bool IsSkinnable
        {
            get
            {
                return false;
            }
        }

        public bool IsValid
        {
            get
            {
                if (!this.invalid)
                {
                    this.invalid = (int)this.type != this.sender.Memory.ReadInteger(this.ptrBase + Addresses.OFFSET_OBJECT_TYPE);
                    this.invalid |= this.ptrStorage != this.sender.Memory.ReadInteger(this.ptrBase + Addresses.OFFSET_OBJECT_STORAGE_POINTER_START);
                    this.invalid |= this.ptrStorageEnd != this.sender.Memory.ReadInteger(this.ptrBase + Addresses.OFFSET_OBJECT_STORAGE_POINTER_END);
                    this.invalid |= this.guid != this.ReadStorageLong(UpdateFields.OBJECT_FIELD_GUID);
                }
                return !this.invalid;
            }
        }

        public virtual int Level
        {
            get
            {
                return 0;
            }
        }

        public virtual int MaximumHealth
        {
            get
            {
                return 0;
            }
        }

        public virtual string Name
        {
            get
            {
                return null;
            }
        }

        public virtual enNodeType NodeType
        {
            get
            {
                return enNodeType.None;
            }
        }

        public virtual long Owner
        {
            get
            {
                return 0L;
            }
        }

        public virtual float Speed
        {
            get
            {
                return 0f;
            }
        }

        public int StoragePtr
        {
            get
            {
                return this.ptrStorage;
            }
        }

        public virtual string SubName
        {
            get
            {
                return null;
            }
        }

        public virtual long SummonGuid
        {
            get
            {
                return 0L;
            }
        }

        internal virtual long TargetGUID
        {
            get
            {
                return 0L;
            }
        }

        public enObjectTypes Type
        {
            get
            {
                return this.type;
            }
        }

        public virtual GameobjectTypes TypeId
        {
            get
            {
                return GameobjectTypes.NONE;
            }
        }

        public virtual int UnitReactionToPlayer
        {
            get
            {
                return -1;
            }
        }

        public virtual float X
        {
            get
            {
                return 0f;
            }
        }

        public virtual float Y
        {
            get
            {
                return 0f;
            }
        }

        public virtual float Z
        {
            get
            {
                return 0f;
            }
        }
    }
}

